package com.nlp.mallet;

import cc.mallet.optimize.LimitedMemoryBFGS;
import cc.mallet.optimize.Optimizable;
import cc.mallet.optimize.Optimizer;
/**
 * 马利特包括数值优化函数的方法。
 * 在机器学习中，数值优化的主要用途是找到使给定观测数据的对数似然函数最大化的参数。
 * 然而，代码是非常通用的，可以用于任意问题。
 * C.Malel.优化包围绕两个接口，可优化和优化器。
 * Optimizable有几个子接口，用于定义不同类型的优化方法。
 * 可优化类是有状态的；它们必须存储所有参数的当前值。
 * 最常用的可优化子接口是Optimizable.ByGradientValue。
 * 实现此接口的类必须提供用于在当前参数设置下计算特定函数的值
 * 和用于计算函数相对于当前参数值的梯度的方法。
 * 注意，该接口不需要二阶导数的Hessian矩阵，因此该接口适合于近似Hessian的数值方法。
 * 下面是一个实现Opjiababel.ByLealTrimeValk的类的示例。
 * 这个类在两个变量中实现了一个非常简单的二次函数。
 * @author ygsong.abcft
 *
 */
public class OptimizerExample implements Optimizable.ByGradientValue{

	double[] parameters;
	
	
	public OptimizerExample(double x, double y) {
		parameters = new double[2];
		parameters[0] = x;
		parameters[1] = y;
	}
	
	@Override
	public int getNumParameters() {
		return 2;
	}

	@Override
	public void getParameters(double[] buffer) {
		buffer[0] = parameters[0];
		buffer[1] = parameters[1];
	}

	@Override
	public double getParameter(int index) {
		return parameters[index];
	}

	@Override
	public void setParameters(double[] params) {
		parameters[0] = params[0];
		parameters[1] = params[1];
		
	}

	@Override
	public void setParameter(int index, double value) {
		parameters[index] = value;
	}

	@Override
	public void getValueGradient(double[] gradient) {
		gradient[0] = -6 * parameters[0] + 2;
		gradient[1] = -8 * parameters[1] - 4;
		
	}

	@Override
	public double getValue() {
		double x = parameters[0];
		double y = parameters[1];
		return -3*x*x - 4*y*y + 2*x - 4*y + 18;
	}

	/**
	 * 既然我们有一个表示可优化函数的类，我们可以把它传递给一个采用这个子接口的优化器。
	 * ByGradientValue子接口与有限内存BFGS优化器兼容，这是一种不需要计算Hessian矩阵的拟牛顿方法。
	 * 	在这个示例中，我们创建一个可优化对象，将其传递给一个新优化器，并优化参数。*/
	public static void main(String[] args) {
		OptimizerExample example = new OptimizerExample(0,0);
		Optimizer optimizer = new LimitedMemoryBFGS(example);
		boolean converged = false;
		try {
			converged = optimizer.optimize();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println(example.getParameter(0)+"   "+example.getParameter(1));
	}
}
